package org.iks.store.business.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.iks.common.ResultCode;
import org.iks.common.exception.BusinessException;
import org.iks.common.pojo.message.ChatMessage;
import org.iks.common.pojo.user.UserInfoVo;
import org.iks.common.util.ServletUtil;
import org.iks.feign.service.user.UserRemoteService;
import org.iks.store.business.entity.SessionEntity;
import org.iks.store.business.entity.SessionMemberEntity;
import org.iks.store.business.mapper.SessionMapper;
import org.iks.store.business.mapper.SessionMemberMapper;
import org.iks.store.business.service.SessionEncipherService;
import org.iks.store.business.service.SessionMessageService;
import org.iks.store.business.service.SessionService;
import org.iks.store.business.vo.secret.SecretCreateItemVo;
import org.iks.store.business.vo.secret.SecretCreateVo;
import org.iks.store.business.vo.session.SessionMessageVo;
import org.iks.store.business.vo.session.SessionVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Author kzou
 * Date 2024/2/13
 * Description:
 */
@Slf4j
@Service
public class SessionServiceImpl extends ServiceImpl<SessionMapper, SessionEntity> implements SessionService {

    @Autowired
    private SessionMemberMapper memberMapper;

    @Autowired
    private UserRemoteService userService;

    @Autowired
    private SessionMessageService messageService;

    @Autowired
    private SessionEncipherService encipherService;

    @Override
    public int createSession(String creatorAccount, List<SecretCreateItemVo> members) {
        // 创建会话
        Map<String, String> memberSec = members
                .stream()
                .distinct()
                .collect(Collectors.toMap(SecretCreateItemVo::getUserAccount, SecretCreateItemVo::getSecretKey));
        if (!memberSec.containsKey(creatorAccount)) {
            throw new BusinessException(ResultCode.PARAMETER_EXCEPTION);
        }
        UserInfoVo userInfoVo = userService.queryUserInfo(creatorAccount).getData();
        SessionEntity sessionEntity = new SessionEntity();
        sessionEntity.setCreateTime(new Date());
        sessionEntity.setName(userInfoVo.getName() + "创建的会话" + RandomUtil.randomString(4));
        //TODO 头像合成
        sessionEntity.setAvatar(userInfoVo.getAvatar());
        sessionEntity.setCreatorAccount(creatorAccount);
        baseMapper.insert(sessionEntity);

        // 添加成员
        Date date = new Date();
        for (String userAccount : memberSec.keySet()) {
            SessionMemberEntity memberEntity = new SessionMemberEntity();
            if(Objects.equals(userAccount, creatorAccount)){
                // 创建者
                memberEntity.setIsCreator(1);
            }
            memberEntity.setCreateTime(date);
            memberEntity.setMemberAccount(userAccount);
            memberEntity.setSessionId(sessionEntity.getId());
            memberMapper.insert(memberEntity);
        }
        // 初始化密钥
        SecretCreateVo secretCreateVo = new SecretCreateVo();
        secretCreateVo.setSecretItems(members);
        secretCreateVo.setSessionId(sessionEntity.getId());
        secretCreateVo.setPreSecretKeyVersion(-1);
        int secretKey = encipherService.createSecretKey(creatorAccount, secretCreateVo);
        log.info("init session：{} secretKey count {}",sessionEntity.getId(), secretKey);
        return sessionEntity.getId();
    }

    @Override
    public void addMember(Integer sessionId, String account) {
        if (checkMemberExist(sessionId, account)) {
            SessionMemberEntity memberEntity = new SessionMemberEntity();
            memberEntity.setMemberAccount(account);
            memberEntity.setSessionId(sessionId);
            memberEntity.setCreateTime(new Date());
            memberMapper.insert(memberEntity);
        }
    }

    @Override
    public List<UserInfoVo> queryMembers(Integer sessionId) {
        SessionEntity sessionEntity = baseMapper.selectById(sessionId);
        Set<String> memberAccounts = new HashSet<>();
        if (sessionEntity.getUserAccount() != null) {
            memberAccounts.add(sessionEntity.getUserAccount());
            memberAccounts.add(sessionEntity.getCreatorAccount());
        } else {
            memberAccounts.add(sessionEntity.getCreatorAccount());
            LambdaQueryWrapper<SessionMemberEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SessionMemberEntity::getSessionId, sessionId);
            List<SessionMemberEntity> memberEntities = memberMapper.selectList(wrapper);
            for (SessionMemberEntity memberEntity : memberEntities) {
                memberAccounts.add(memberEntity.getMemberAccount());
            }
        }
        return memberAccounts
                .stream()
                .map(it -> userService.queryUserInfo(it).data())
                .collect(Collectors.toList());
    }

    @Override
    public void deleteMember(Integer sessionId, String userAccount) {
        LambdaQueryWrapper<SessionMemberEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(SessionMemberEntity::getSessionId, sessionId)
                .eq(SessionMemberEntity::getMemberAccount, userAccount);
        memberMapper.delete(queryWrapper);
    }

    @Override
    public List<SessionMessageVo> querySessionMessageList(String userAccount) {
        List<SessionMessageVo> sessionMessageVos = baseMapper.querySessionMessageList(userAccount);
        for (SessionMessageVo sessionMessageVo : sessionMessageVos) {
            Integer sessionId = sessionMessageVo.getSessionId();
            ChatMessage chatMessage = messageService.queryLatestMessage(sessionId);
            sessionMessageVo.setLatestMessage(chatMessage);
        }
        String account = ServletUtil.currUser().account();
        Set<String> defaultSessionAccount = sessionMessageVos
                .stream()
                .filter(e -> e.getUserAccount() != null)
                .map(e -> Objects.equals(e.getUserAccount(), account)
                        ? e.getCreatorAccount()
                        : e.getUserAccount()
                )
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (defaultSessionAccount.isEmpty()) {
            return sessionMessageVos;
        }

        Map<String, UserInfoVo> userInfoVoMap = userService
                .queryUserInfoBatch(defaultSessionAccount)
                .data()
                .stream()
                .collect(Collectors.toMap(UserInfoVo::getAccount, e -> e));

        return sessionMessageVos
                .stream()
                .filter(e -> e.getUserAccount() == null || userInfoVoMap.containsKey(e.getUserAccount()))
                .peek(e -> {
                    String friendAccount = Objects.equals(e.getUserAccount(), account)
                            ? e.getCreatorAccount()
                            : e.getUserAccount();
                    UserInfoVo userInfoVo = userInfoVoMap.get(friendAccount);
                    if (userInfoVo != null) {
                        e.setAvatar(userInfoVo.getAvatar());
                        e.setSessionName(userInfoVo.getName());
                    }
                })
                .toList();
    }

    @Override
    public SessionVo querySession(Integer sessionId) {
        SessionVo sessionVo = baseMapper.querySession(sessionId);
        if (sessionVo.getUserAccount() != null) {
            // 默认会话
            String currAccount = ServletUtil.currUser().account();
            String account = Objects.equals(currAccount, sessionVo.getUserAccount())
                    ? sessionVo.getCreatorAccount()
                    : sessionVo.getUserAccount();
            UserInfoVo userInfoVo = userService.queryUserInfo(account).data();
            sessionVo.setAvatar(userInfoVo.getAvatar());
            sessionVo.setName(userInfoVo.getName());
        }
        return sessionVo;
    }

    @Override
    public int queryUnReadMessageCount(Integer sessionId, String userAccount) {
        return baseMapper.queryUnreadCount(sessionId, userAccount);
    }

    @Override
    public Integer queryUserDefaultSession(String userAccount) {
        String account = ServletUtil.currUser().account();
        SessionEntity sessions = baseMapper.queryUserDefaultSession(userAccount, account);
        if (sessions == null) {
            return null;
        }
        return sessions.getId();
    }

    @Override
    public Integer createUserDefaultSession(String userAccount) {
        Integer sessionId = queryUserDefaultSession(userAccount);
        if (sessionId != null) {
            return sessionId;
        }
        String account = ServletUtil.currUser().account();
        SessionEntity sessionEntity = new SessionEntity();
        sessionEntity.setName("");
        sessionEntity.setAvatar("");
        sessionEntity.setCreatorAccount(account);
        sessionEntity.setCreateTime(new Date());
        sessionEntity.setUpdateTime(new Date());
        sessionEntity.setUserAccount(userAccount);
        baseMapper.insert(sessionEntity);
        return sessionEntity.getId();
    }

    public boolean checkMemberExist(Integer sessionId, String account) {
        LambdaQueryWrapper<SessionMemberEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SessionMemberEntity::getSessionId, sessionId)
                .eq(SessionMemberEntity::getMemberAccount, account);
        return memberMapper.exists(queryWrapper);
    }

}
